package com.weds.frame.auth.service;

import com.alibaba.fastjson.JSONObject;
import com.weds.frame.auth.config.JWTProperties;
import com.weds.frame.auth.entity.base.JWTCreateResponse;
import com.weds.frame.auth.entity.base.JWTParseResponse;
import com.weds.frame.common.util.AESUtil;
import com.weds.frame.common.util.StringUtils;
import com.weds.frame.core.util.RedisUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2023/3/17 10:13
 */
@Service
@Slf4j
public class TokenService {

    @Autowired
    private RedisUtil redis;
    static int kid = 0;
    static int pkeyid = 1;
    @Resource
    private JWTProperties jwtProperties;

    public JWTCreateResponse createToken(JSONObject pdata, String issuer, String subject, String aud) {
        JWTCreateResponse jwtCreateResponse = new JWTCreateResponse();
        String userID = pdata.getString("userID");
        if (StringUtils.isEmpty(userID)) {
            jwtCreateResponse.setCode("-1");
            jwtCreateResponse.setMessage("pdata中请传入userID");
            return jwtCreateResponse;
        }

        String redisKey = userID + "_" + aud + "_login";
        if (!jwtProperties.isKick()) {
            // 不互踢的情况
            if (redis.keyExist(redisKey)) {
                // redis有值 返回
                jwtCreateResponse.setCode("1");
                jwtCreateResponse.setData(redis.getString(redisKey));
                return jwtCreateResponse;
            }
        }


        List<String> keys = Arrays.asList(this.jwtProperties.getSecretKey().split(","));
        List<JSONObject> pkeys = new ArrayList();
        List<String> pJson = Arrays.asList(this.jwtProperties.getSecretPkey().split(","));
        Iterator var12 = pJson.iterator();

        while (var12.hasNext()) {
            String json = (String) var12.next();
            String[] values = json.split("&");
            JSONObject pvalue = new JSONObject();
            pvalue.put("key", values[0]);
            pvalue.put("iv", values[1]);
            pkeys.add(pvalue);
        }
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        byte[] apiKeySecretBytes = (keys.get(kid)).getBytes();
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        JwtBuilder builder = Jwts.builder().setIssuedAt(now).setSubject(subject).setIssuer(issuer).signWith(signatureAlgorithm, signingKey);
        // 暂不设置过期时间
        Map<String, Object> header = new HashMap();
        header.put("typ", "JWT");
        header.put("alg", "HS256");
        header.put("kid", String.valueOf(kid));
        builder.claim("palg", "aes-256-cbc");
        builder.claim("pkeyid", String.valueOf(pkeyid));
        builder.claim("jti", userID + aud + "login");
        builder.claim("aud", aud);
        builder.setHeader(header);
        JSONObject pDataRam = new JSONObject();
        pDataRam.put("random", this.getRandom());
        pDataRam.putAll(pdata);
        JSONObject pkeyData = pkeys.get(pkeyid);
        String encrypted = AESUtil.encrypt(pDataRam.toJSONString(), pkeyData.get("key").toString(), pkeyData.get("iv").toString());
        builder.claim("pdata", encrypted);
        String tokenPlain = builder.compact();
        byte[] encodedBytes = Base64.encodeBase64(tokenPlain.getBytes());
        String creToken = new String(encodedBytes);
        redis.put(redisKey, creToken, 3, TimeUnit.DAYS);
        jwtCreateResponse.setCode("0");
        jwtCreateResponse.setData(creToken);
        return jwtCreateResponse;
    }

    public JWTParseResponse parseToken(String token) {
        JWTParseResponse jwtParseResponse = new JWTParseResponse();
        try {
            List<String> keys = Arrays.asList(this.jwtProperties.getSecretKey().split(","));
            List<JSONObject> pkeys = new ArrayList();
            List<String> pJson = Arrays.asList(this.jwtProperties.getSecretPkey().split(","));
            Iterator var8 = pJson.iterator();

            String pdata;
            while (var8.hasNext()) {
                pdata = (String) var8.next();
                String[] values = pdata.split("&");
                JSONObject pvalue = new JSONObject();
                pvalue.put("key", values[0]);
                pvalue.put("iv", values[1]);
                pkeys.add(pvalue);
            }
            Claims claims = Jwts.parser().setSigningKey((keys.get(kid)).getBytes()).parseClaimsJws(token).getBody();
            pdata = claims.get("pdata").toString();
            JSONObject pkeyData = (JSONObject) pkeys.get(pkeyid);
            String pdataStr = AESUtil.decrypt(pdata, pkeyData.get("key").toString(), pkeyData.get("iv").toString());
            JSONObject pdataJson = JSONObject.parseObject(pdataStr);
            if (!redis.keyExist(pdataJson.getString("userID") + "_" + claims.get("aud") + "_login")) {
                jwtParseResponse.setCode("-1");
                jwtParseResponse.setMessage("令牌过期");
                return jwtParseResponse;
            } else {
                jwtParseResponse.setCode("0");
                jwtParseResponse.setMessage("success");
                jwtParseResponse.setPdata(pdataStr);
                return jwtParseResponse;
            }
        } catch (Exception e) {
            e.printStackTrace();
            jwtParseResponse.setCode("-1");
            jwtParseResponse.setMessage("令牌解析异常");
            return jwtParseResponse;
        }
    }

    private String getRandom() {
        return String.valueOf((new Random()).nextDouble());
    }
}
